package com.xushuda.yas.storage;

/**
 * Created by xushuda on 14/12/30.
 *
 */
import java.io.IOException;

public class BFilter {

    private String pathName = "/opt/yas_default.bf"; // TODO

    private int size = 1 << 25; // TODO

    private static final int[] seeds = new int[] { 5, 7, 11, 13, 31, 37, 61 };

    // this set use singleton, one path only generate one bloom filter
    private MmBit bits;

    private HashFunctor[] funcs = new HashFunctor[seeds.length];

    public BFilter() throws IOException {
        init(pathName, size);
    }

    public BFilter(String pathName, int size) throws IOException {
        this.pathName = pathName;

        this.size = size;

        init(pathName, size);
    }

    private void init(String pathName, int size) throws IOException {

        for (int i = 0; i < seeds.length; i++) {
            funcs[i] = new HashFunctor(size, seeds[i]);
        }

        bits = MmBit.getInstance(pathName, size);
    }

    public void add(String value) {
        for (HashFunctor f : funcs) {
            bits.set(f.hash(value), true);
        }
    }

    public boolean contains(String value) {
        if (value == null) {
            return false;
        }
        boolean ret = true;
        for (HashFunctor f : funcs) {
            // todo can be optimized
            ret = ret && bits.get(f.hash(value));
        }
        return ret;
    }

    // inner class, provide functions
    public static class HashFunctor {
        private int cap;
        private int seed;

        public HashFunctor(int cap, int seed) {
            this.cap = cap;
            this.seed = seed;
        }

        public int hash(String value) {
            int result = 0;
            int len = value.length();
            for (int i = 0; i < len; i++) {
                result = seed * result + value.charAt(i);
            }
            return (cap - 1) & result;
        }

    }

}